package mysql

import (
	"context"
	"go.uber.org/zap"
	"gorm.io/gorm"
	log "maya-service/collector/logger"
	"maya-service/config"
	"maya-service/errors"
	"maya-service/model"
	"maya-service/model/entity"
	"maya-service/utils"
)

var AiQuestion = &aiQuestion{}

type aiQuestion struct{}

func init() {
	Register(AiQuestion)
}

func (a *aiQuestion) Init() {
	if config.Conf.AutoMigrate {
		p := &entity.AiQuestion{}
		if db.Migrator().HasTable(p) {
			log.Debug("table already exist: ", zap.String("table", p.TableName()))
			return
		}
		if err := db.AutoMigrate(p); err != nil {
			log.Error("filed to create table please check config or manually create", zap.String("table", p.TableName()), zap.String("err", err.Error()))
		} else {
			log.Info("create table successfully", zap.String("table", p.TableName()))
		}
	}
}

// Create
func (a *aiQuestion) Create(ctx context.Context, m *entity.AiQuestion) (int64, error) {
	err := GetDB(ctx).Create(m).Error
	return m.Id, err
}

// Find detail
func (a *aiQuestion) Find(ctx context.Context, in *model.AiQuestionInfoRequest) (*entity.AiQuestion, error) {
	e := &entity.AiQuestion{}

	q := GetDB(ctx).Model(&entity.AiQuestion{})

	if in.Id == 0 {
		return e, errors.New("condition illegal")
	}
	err := q.Where("id = ?", in.Id).First(&e).Error
	return e, err
}

// Update
func (a *aiQuestion) Update(ctx context.Context, id int64, dict map[string]interface{}) error {
	return GetDB(ctx).Model(&entity.AiQuestion{}).Where("id = ?", id).Updates(dict).Error
}

// Delete
func (a *aiQuestion) Delete(ctx context.Context, in *model.AiQuestionDeleteRequest) error {
	if in.ModuleId > 0 {
		return GetDB(ctx).Where("module = ?", in.ModuleId).Delete(&entity.AiQuestion{}).Error
	}

	if len(in.Ids) > 0 {
		return GetDB(ctx).Where("id in ?", in.Ids).Delete(&entity.AiQuestion{}).Error
	}

	return GetDB(ctx).Where("id = ?", in.Id).Delete(&entity.AiQuestion{}).Error
}

// List query list
func (a *aiQuestion) List(ctx context.Context, in *model.AiQuestionListRequest) (int, []*entity.AiQuestion, error) {
	var (
		q           = GetDB(ctx).Model(&entity.AiQuestion{})
		err         error
		total       int64
		aiQuestions []*entity.AiQuestion
	)

	if in.Topic != nil {

		q = q.Where("topic like ?", utils.SqlLike(in.Topic))

	}

	if in.Content != nil {

		q = q.Where("content like ?", utils.SqlLike(in.Content))

	}

	if in.Level != nil {

		q = q.Where("level = ?", in.Level)

	}

	if in.Module != nil {

		q = q.Where("module = ?", in.Module)

	}

	if in.Weight != nil {
		q = q.Where("weight = ?", in.Weight)
	}

	if in.CreatedAt != nil {

		q = q.Where("created_at = ?", in.CreatedAt)

	}

	if in.UpdatedAt != nil {

		q = q.Where("updated_at = ?", in.UpdatedAt)

	}

	if in.ProductId != nil {
		q = q.Where("product_id = ?", in.ProductId)
	}

	if in.Issue != nil {
		q = q.Where("issue = ?", in.Issue)
	}

	if in.Questioner != nil {
		q = q.Where("questioner = ?", utils.SqlLike(in.Questioner))
	}

	if in.CollectorId != nil {
		q = q.Where("collector_id = ?", in.CollectorId)
	}

	if in.UpDown != nil {
		q = q.Where("up_down = ?", in.UpDown)
	}

	if in.IsRecommend != nil && *in.IsRecommend > 0 {
		q = q.Where("recommend_strength > 0")
	}

	if in.IsRecommend != nil && *in.IsRecommend == 0 {
		q = q.Where("recommend_strength == 0")
	}

	if in.CourseType != nil {
		q = q.Where("course_type = ?", in.CourseType)
	}

	if in.IsFilterOld {
		q = q.Where("course_type > ?", 0)
	}

	if err = q.Count(&total).Error; err != nil {
		return 0, nil, err
	}

	if in.OrderByHeat {
		q = q.Order("heat desc, id desc")
	} else if in.IsRecommendList {
		q = q.Order("recommend_strength desc, id desc")
	} else {
		if in.Weight != nil {
			q = q.Order("weight desc, id desc")
		} else {
			q = q.Order("id desc")
		}
	}

	if err = q.Limit(in.Size).Offset((in.Index - 1) * in.Size).Find(&aiQuestions).Error; err != nil {
		return 0, nil, err
	}
	return int(total), aiQuestions, nil
}

// ExecTransaction execute database transaction
func (a *aiQuestion) ExecTransaction(ctx context.Context, callback func(ctx context.Context) error) error {
	return GetDB(ctx).Transaction(func(tx *gorm.DB) error {
		ctx = context.WithValue(ctx, ContextTxKey, tx)
		return callback(ctx)
	})
}
